home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
12A.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
35KB
|
1,125 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
/* chapter 12 - part a*/
#include "hdr.h"
#include "vars.h"
#include "libhdr.h"
#include "attr.h"
#include "unitsp.h"
#include "errmsgp.h"
#include "miscp.h"
#include "smiscp.h"
#include "setp.h"
#include "libp.h"
#include "dclmapp.h"
#include "nodesp.h"
#include "chapp.h"
static Tuple collect_generic_formals(Node);
static void add_implicit_neq(Tuple, Node, Symbol);
static void bind_names(Node);
void generic_subprog_spec(Node node) /*;generic_subprog_spec*/
{
int nat, kind, i;
Node id_node, generic_part_node, ret_node, formals_list;
int f_mode, body_number;
char *obj_id;
Symbol gen_name, form_name, scope;
Tuple gen_list, form_list;
Tuple tup;
Node formal_node, id_list, m_node, type_node, exp_node, init_node;
Symbol type_mark;
Tuple f_ids;
char *id;
Fortup ft1, ft2;
/*
* Build specifications of a generic subprogram. We create a scope for
* it, and define within the names of generics and formal parameters.
* The signature of the generic subprogram includes the generic parameter
* list and the formals. These two are unpacked during instantiation.
*/
if (cdebug2 > 3)
TO_ERRFILE("AT PROC : generic_subprog_spec ");
id_node = N_AST1(node);
generic_part_node = N_AST2(node);
formals_list = N_AST3(node);
ret_node = N_AST4(node);
kind = N_KIND(node);
obj_id = N_VAL(id_node);
new_compunit("ss", id_node);
if (IS_COMP_UNIT) {
/* allocate unit number for body, and mark it obsolete */
body_number = unit_number(strjoin("su", obj_id));
pUnits[body_number]->libInfo.obsolete = string_ds; /*"$D$"*/
}
gen_name = find_new(obj_id);
N_UNQ(id_node) = gen_name;
DECLARED(gen_name) = dcl_new(0);
NATURE(gen_name) = na_generic_part;
formal_decl_tree(gen_name) = (Symbol) formals_list;
newscope(gen_name);
adasem(generic_part_node);
gen_list = collect_generic_formals(generic_part_node);
/*
* Now declared(gen_name) contains the generic parameters: types,
* objects and subprograms.
*
* For the formal parameters, we simply must recognize their names
* and types. Type checking on initialization is repeated on
* instantiation.
*/
NATURE(gen_name) = na_void; /* To catch premature usage. */
form_list = tup_new(0);
FORTUP(formal_node =(Node), N_LIST(formals_list), ft1);
id_list = N_AST1(formal_node);
m_node = N_AST2(formal_node);
type_node = N_AST3(formal_node);
exp_node = N_AST4(formal_node);
type_mark = find_type(copy_tree(type_node));
if (exp_node != OPT_NODE) {
adasem(exp_node);
init_node = copy_tree(exp_node);
normalize(type_mark, init_node);
}
else init_node = OPT_NODE;
current_node = formal_node;
f_ids = tup_new(tup_size(N_LIST(id_list)));
FORTUPI(id_node=(Node), N_LIST(id_list), i, ft2);
f_ids[i] = N_VAL(id_node);
ENDFORTUP(ft2);
f_mode = (int) N_VAL(m_node);
if (f_mode == 0 ) f_mode = na_in;
FORTUP(id=, f_ids, ft2);
form_name = find_new(id);
NATURE(form_name) = f_mode;
TYPE_OF(form_name) = type_mark;
default_expr(form_name) = (Tuple) copy_tree(init_node);
form_list = tup_with(form_list, (char *) form_name);
ENDFORTUP(ft2);
if (f_mode != na_in && kind == as_generic_function) {
errmsg_l(nature_str(f_mode),
" parameter not allowed for functions", "6.5", formal_node);
}
/* enforce restrictions on usage of out formal parameters given in
* LRM 7.4.4
*/
scope = SCOPE_OF(type_mark);
nat = NATURE(scope);
if (f_mode != na_out || is_access(type_mark))
continue;
else if (TYPE_OF(type_mark) == symbol_limited_private
&& (nat == na_package_spec || nat == na_generic_package_spec
|| nat == na_generic_part )
&& !in_private_part(scope)
&& tup_mem((char *)scope, open_scopes) ) {
/* We are in the visible part of the package that declares
* the type. Its full decl. will have to be given with an
* assignable type.
*/
misc_type_attributes(type_mark) =
(misc_type_attributes(type_mark)) | TA_OUT;
}
else if (is_limited_type(type_mark)) {
errmsg_id("Invalid use of limited type % for out parameter ",
type_mark, "7.4.4", formal_node);
}
ENDFORTUP(ft1);
/*
* Save signature of generic object, in the format which the
* instantiation procedure requires.
*/
NATURE(gen_name) =
(kind == as_generic_procedure) ? na_generic_procedure_spec
: na_generic_function_spec;
tup = tup_new(4);
tup[1] = (char *) gen_list;
tup[2] = (char *) form_list;
tup[3] = (char *) OPT_NODE;
tup[4] = (char *) tup_new(0);
SIGNATURE(gen_name) = tup;
if (kind == as_generic_function) {
find_old(ret_node);
TYPE_OF(gen_name) = N_UNQ(ret_node);
}
else {
TYPE_OF(gen_name) = symbol_none;
}
popscope();
save_subprog_info(gen_name);
}
void generic_subprog_body(Symbol prog_name, Node node) /*;generic_subprog_body*/
{
/*
* Within its body, the generic subprogram name behaves as a regular
* (i.e. non-generic) subprogram. In particular, it can be called (and
* it cannot be instantiated). Its nature must be set accordingly, prior
* to compilation of the body.
*/
int new_nat, nat, i;
Tuple sig, must_constrain;
Node specs_node, decl_node, formals_node;
char *spec_name;
char *junk;
Tuple specs, tup, gen_list, form_list, decscopes, decmaps, body_specs;
Symbol generic_sym, g_name;
Unitdecl ud;
Fortup ft;
/* if module is a generic subprogram body verify that the generic spec
* appeared in the same file.
*/
if (IS_COMP_UNIT) {
spec_name = strjoin("ss", unit_name_name(unit_name));
if (!streq(lib_unit_get(spec_name), AISFILENAME))
errmsg("Separately compiled generics not supported", "none", node);
}
if (NATURE(prog_name) == na_generic_procedure_spec) {
new_nat = na_procedure;
nat = na_generic_procedure; /* Save till end of body. */
}
else {
new_nat = na_function;
nat = na_generic_function;
}
/*
* save and stack the generic symbol for this subprogram to allow the
* detection of recursive instantiations within the generic body
*/
generic_sym = sym_new_noseq(na_void);
sym_copy(generic_sym, prog_name);
NATURE(generic_sym) = nat;
current_instances = tup_with(current_instances, (char *) generic_sym);
NATURE(prog_name) = new_nat;
/*
* The signature of a generic object includes the generic part. During
* compilation of the body, set the signature to contain only the formals
*/
sig = SIGNATURE(prog_name);
gen_list = (Tuple) sig[1];
form_list = (Tuple) sig[2];
SIGNATURE(prog_name) = (Tuple) form_list;
OVERLOADS(prog_name) = set_new1((char *) prog_name);
specs_node = N_AST1(node);
formals_node = N_AST2(specs_node);
decl_node = N_AST2(node);
newscope(prog_name);
reprocess_formals(prog_name, formals_node);
process_subprog_body(node, prog_name);
force_all_types();
popscope();
/*
* If a generic subprogram parameter is an equality operator, we must
* construct the body for the corresponding implicitly defined inequality
*/
add_implicit_neq(gen_list, decl_node, prog_name);
/* Outside of its body, the object is generic again.*/
NATURE(prog_name) = nat;
junk = tup_frome(current_instances);
/* collect all generic types whose '$constrain' attribute is set into the
* tuple must_constrain and save it in the signature of the body
*/
must_constrain = tup_new(0);
FORTUP(tup=(Tuple), gen_list, ft)
g_name = (Symbol)tup[1];
if ((int)misc_type_attributes(g_name) & TA_CONSTRAIN)
must_constrain = tup_with(must_constrain, (char *)g_name);
ENDFORTUP(ft)
sig= tup_new(4);
sig[1] = (char *) gen_list;
sig[2] = (char *) form_list;
sig[3] = (char *) node;
sig[4] = (char *) must_constrain;
SIGNATURE(prog_name) = sig; /* for instantiation */
OVERLOADS(prog_name) = (Set) 0; /* Not a callable object. */
/*
* If the corresponding spec was defined in another compilation unit, it
* must be updated accordingly. If the generic is not itself a compila-
* tion unit, we find the unit in which it appears, and upda